/*
 * author: Andriamananony, Meß, Falk
 */

package start;

import java.util.ArrayList;
import java.util.Map.Entry;

import plan.Plan;
import schedule.IterateProductOrderFlood;
import schedule.IterateProductOrderThreshold;
import schedule.SimplePlan;
import util.JSONParser;
import util.TimeLog;
import auftrag.Auftrag;
import auftrag.Produkt;
import auftrag.Ressource;
import constraints.AllOrdersPlanned;
import constraints.DueDate;
import constraints.IConstraint;
import constraints.NoMachineOverload;
import constraints.OperationOrder;

public class Start {
	public static int it = 0;
	public static void main(String[] args) {
		int it = 2;
		//parser.print();
		/**
		 * Wir nutzen zwei Verfahren: -iteriere über verschiedenen Varianten für
		 * die Produkte -iteriere über die Reihenfolge der Produkte bei der
		 * Einplanung
		 * 
		 * Annahme: Zwei Aufträge sind dann in einer Nachbarschaft, wenn die
		 * Reihenfolge, mit der ihre Produkte einsortiert werden, ähnlich sind,
		 * oder sie sich nur in Varianten unterscheiden
		 * 
		 * Beobachtungen: Das iterative Verfahren über Varianten zeigt schnellen
		 * Erfolg, wohl weil dadurch die Last langsam gleichmäßig auf alle
		 * Maschinen verteilt wird. Das ändern der Reihenfolge von Produkten
		 * nach dem Zufallsprinzip bringt allerdings gemessen an der Laufzeit
		 * nur geringen Erfolg, wohl weil es zu viele gleichartige Produkte
		 * gibt.
		 * 
		 * Möglich ist, dass eine Kombination der beiden noch schneller zu
		 * besseren Ergebnissen führt! (Memo an mich selbst: Für Contest
		 * testen!)
		 */
		for (int i = 0; i < it; i++) {
			Start.it = 0;
			JSONParser parser = new JSONParser("bigbeispieldata.json");
			TimeLog.logInfo("=============================================");
			TimeLog.logInfo("=== Plan " + i);
			TimeLog.logInfo("=============================================");

			Plan p = new Plan();
			p = new SimplePlan().makePlan(parser.getOrders(), parser.getRessources());
			System.out.println(p.getQuality(true));

			for (Ressource r : parser.getRessources())
				r.clear();

			if (i == 0) {
				// Im ersten Schritt wird ein Verfahren getestet, das die
				// Variante für ein zufälliges Produkt ändert
				IterateProductOrderFlood ipo = new IterateProductOrderFlood();
				p = ipo.makePlan(parser.getOrders(), parser.getRessources());
			} else {
				// Im zweiten Schritt wird ein Verfahren getestet, das in jedem
				// Schritt die Reihenfolge von ein oder zwei Produkten ändert
				IterateProductOrderThreshold ipo = new IterateProductOrderThreshold();
				p = ipo.makePlan(parser.getOrders(), parser.getRessources());
			}

			TimeLog.logInfo("Plan created!");

			//p.print();

			// Prüfen der Constraints
			IConstraint c1 = new AllOrdersPlanned();
			IConstraint c2 = new NoMachineOverload();
			IConstraint c3 = new OperationOrder();
			IConstraint c4 = new DueDate();


			/*for (Auftrag a : parser.getOrders()) {
				System.out.println("Auftragsnummer: " + a.getAuftragsnummer()
						+ "\t || Soll Startzeit: "+a.getEarliestStartTime()
						+ "\t || Ist Startzeit: "+a.getStartDate()
						+ "\t || Auftragsende: " + a.getEndDate()
						+ "\t || Auftragsdeadline: " + a.getDeadline()
						+ "\t || Auftragspriorität: " + a.getPriority());
			}*/
			

			if (c1.isMetBy(p, parser.getOrders())) {
				System.out.println("Alle Aufträge eingeplant!");
			}
			if (c2.isMetBy(p, parser.getOrders())) {
				System.out.println("Keine Doppelbelegung!");
			}
			if (c3.isMetBy(p, parser.getOrders())) {
				System.out.println("Produktionsreihenfolge eingehalten!");
			}
			if (c4.isMetBy(p, parser.getOrders())) {
				System.out.println("Alle Aufträge pünktlich abgearbeitet!");
			}
			
			System.out.println(p.getQuality(true));
			
			for(Ressource r : parser.getRessources())
				if(r.getMaxTime() > 0)
					System.out.println(r+": "+r.getAuslastung());
			
			long sumProducts = 0;
			for(Entry<String, ArrayList<Produkt>> e : parser.getProducts().entrySet()){
				sumProducts += e.getValue().size();
				System.out.println(e.getKey()+": "+e.getValue().size());
			}
			System.out.println("Allover: "+sumProducts);
			
			long sumPlannedProducts = 0;
			for(Auftrag a : parser.getOrders()){
				if(a.getEarliestStartTime() < a.getEndDate())
					sumPlannedProducts += a.getAuftragProdukteSize();
			}
			System.out.println("Planned: "+sumPlannedProducts);
			System.out.println(Start.it);
		}

	}
}
